﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices.Protocols;
using System.Diagnostics.Contracts;
using System.Net;
using System.DirectoryServices;
using FoundationLib.Logging;
using FoundationLib.Ifc.Authorisation;
using FoundationLib.Ifc.Logging;

namespace FoundationLib.Authorisation
{
	/// <summary>
	/// This class represents an authorisation service for LDAP.
	/// </summary>
	public class LdapAuthorisationService : AuthorisationService
	{
		/// <summary>
		/// Creates a new <see cref="LdapAuthorisationService"/>.
		/// </summary>
		public LdapAuthorisationService()
			: base()
		{
		}

		/// <see cref="AuthorisationServiceBase.Authorise(string, string)"/>
		public override bool Authorise(string username, string password)
		{			
			try
			{
				using (LdapConnection connection = new LdapConnection(
					new LdapDirectoryIdentifier(this.Configuration.Server, this.Configuration.Port)))
				{
					connection.AuthType = AuthType.Basic;
					connection.Bind(new NetworkCredential(this.Configuration.BindUserDn, this.Configuration.BindUserPassword));

					SearchRequest request = new SearchRequest(this.Configuration.BaseDn, 
						String.Format("(&(objectClass=Person)({0}={1}))", this.Configuration.UidAttribute, username),
						System.DirectoryServices.Protocols.SearchScope.Subtree);

					SearchResponse response = connection.SendRequest(request) as SearchResponse;
					if (response.Entries.Count == 0)
						return false;

					SearchResultEntry entry = response.Entries[0];
					string dn = entry.DistinguishedName;

					connection.Bind(new NetworkCredential(dn, password));
				}

				return true;
			}
			catch (Exception ex)
			{
				LogManager.TechnicalLogger.Warn(ex);
				return false;
			}
		}
	}
}
